home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_07_03
/
v7n3061a.txt
< prev
next >
Wrap
Text File
|
1989-01-16
|
17KB
|
463 lines
Listing1
/* define WORD to be signed sixteen bit integer */
#ifdef MEGAMAX
#define WORD int
#else
#define WORD short
#endif
typedef struct
{
WORD activation; /* activation of neuron for feedforward */
WORD errors; /* sum of errors from feedback */
} NEURON;
#define NEURON_SIZE 4 /* sizeof(NEURON) for assembler */
#define O_ERROR 2 /* offset of neuron.errors for assembler */
#define ACTIVATION_SHIFT 7 /* units of 1/128: 2**-7 */
#define RATE_SHIFT 7 /* units of 1/128: 2**-7 */
Listing2
typedef WORD SYNAPSE;
#define MAX_SYNAPSE 32767
#define SYNAPSE_SHIFT 10 /* units of 1/1024: 2**-10 */
typedef struct layer
{
struct layer *prev_layer; /* pointer to previous layer, if any */
int n_inputs; /* number of input neurons */
NEURON *inputs; /* same address as outputs of previous layer*/
SYNAPSE *synapses; /* synapses[n_inputs][n_outputs] */
SYNAPSE *history; /* previous values for use in learning */
char rate; /* learning rate, larger values learn faster*/
char momentum; /* learning momentum in powers of two, 0 to 7 */
int n_outputs; /* number of output neurons */
NEURON *outputs; /* same address as inputs of next layer */
struct layer *next_layer; /* pointer to next layer, if any */
} LAYER;
typedef struct
{
LAYER *first_layer;
LAYER *last_layer;
} NETWORK;
Listing3
transfer(n_inputs, inputs, output, synapses)
register int n_inputs; /* number of input neurons */
register NEURON *inputs; /* vector of input neurons */
NEURON *output; /* output neuron */
register SYNAPSE *synapses; /* vector of synapses on */
{
register long sum = 0; /* for accumulating inputs */
long i; /* for intermediate */
/* feed input activation forward through synapses by accumulating
products */
#ifndef MEGAMAX
while (--n_inputs >= 0)
sum += (long) * synapses++*(inputs++)->activation;
#else /* use Megamax inline assembly for Motorola */
asm
{
bra test
loop:
;
while (--n_inputs >= 0)
move.w(synapses) + , D0;
D0 = *synapses++muls(inputs), D0;
D0 *= input->activation addq.l#NEURON_SIZE, inputs;
input++add.l D0, sum;
sum += D0
test:
dbf n_inputs, loop
}
#endif
/* limit activation overload with log if below -100 or above 100) */
if (sum > 0)
{
sum += 1 << SYNAPSE_SHIFT - 1; /* round sum */
sum >>= SYNAPSE_SHIFT; /* shift sum back into range */
if (sum > 100) /* sum = 100 + log2(sum-100) */
for (i = sum, sum = 100; (i >>= 1) >= 100; sum++)
;
}
else if (sum < 0)
{
sum -= 1 << SYNAPSE_SHIFT - 1; /* round sum */
sum >>= SYNAPSE_SHIFT; /* shift sum back into range */
if (sum < -100) /* sum = -100 - log2(-sum-100) */
for (i = -sum, sum = -100; (i >>= 1) >= 100; sum--)
;
}
output->activation = sum;
}
Listing4
error(n_inputs, inputs, output, synapses, history, rate, momentum)
register int n_inputs; /* number of input neurons */
register NEURON *inputs; /* vector of input neurons */
NEURON *output; /* output neuron */
register SYNAPSE *synapses; /* vector of synapses on output */
SYNAPSE *history; /* vector of synapse history */
int rate; /* transfer learning rate */
int momentum; /* if true use synapse history */
{
WORD error; /* correction error for synapse */
long weight; /* synapse weight */
long feedback; /* amount to feedback to previous layer */
long delta; /* amount to change synapse weight */
/* amount of left shift to bring feedback and delta back into proper
range */
#define FEEDBACK_SHIFT \
SYNAPSE_SHIFT+ACTIVATION_SHIFT+RATE_SHIFT-ACTIVATION_SHIFT
#define DELTA_SHIFT \
ACTIVATION_SHIFT+ACTIVATION_SHIFT+RATE_SHIFT-SYNAPSE_SHIFT
/* get error, factor in derivative of log limit function if overload*/
error = output->errors;
if (output->activation > 100)
error = (error * 100) / output->activation;
else if (output->activation < -100)
error = (error * 100) / output->activation;
error *= rate; /* error proportional to learning rate */
#ifndef MEGAMAX
while (--n_inputs >= 0) /* calculate new synapse weights: */
{
weight = *synapses; /* get weight from synapse */
feedback = weight; /* feedback proportional to weight */
feedback *= error; /* feedback proportional to error */
feedback >>= FEEDBACK_SHIFT; /* shift feedback into range of
errors */
inputs->errors += feedback; /* feedback to input errors */
delta = inputs->activation; /* delta proportional to input */
inputs++; /* next input */
delta *= error; /* delta proportional to error */
delta >>= DELTA_SHIFT; /* shift delta into range of weight */
if (momentum)
{
delta += *history; /* add momentum to delta */
*history++ = (SYNAPSE)delta; /* save delta for next
feedback cycle */
}
weight += delta; /* synapse weight corrected by delta */
if (weight > MAX_SYNAPSE)
weight = MAX_SYNAPSE; /* limit weight in case of overflow */
else if (weight < -MAX_SYNAPSE)
weight = -MAX_SYNAPSE; /* limit weight in case of underflow */
*/
*synapses++ = (SYNAPSE)weight; /* put new weight back in synapse*/
}
#else /* use Megamax inline assembly for Motorola */
asm
{
move.w history(A6), A1;
A1 = history move.w momentum(A6), D2;
D2 = momentum move.w error(A6), D3;
D3 = error move.w#FEEDBACK_SHIFT, D4;
D4 = shift factorfor feedback move.w#DELTA_SHIFT, D5;
D5 = shift factorfor delta bra end;
loop:; while (--n >= 0)
;
get weight from synapse clr.l D0;
weight = 0L move.w(synapses), D0;
weight = *synapse;
feedback error to inputs move.w D0, D1;
feedback = weight muls D3, D1;
feedback *= error asr.l D4, D1;
feedback >>= FEEDBACK_SHIFT add.w D1, O_ERROR()(inputs);
inputs->errors += feedback;
delta proportional to input move.w(inputs), D1;
delta = inputs->activation adda.l#NEURON_SIZE, inputs;
inputs++;
delta proportional to error muls D3, D1;
delta *= error asr.l D5, D1;
delta >>= DELTA_SHIFT;
add momentum to delta cmp.w#0, D2;
if (0 != momentum)
beq.s mod;
add.w(A1), D1;
delta += *history move.w D1, (A1) + ;
*history++ = delta;
modify weight by delta ext.l D1;
(long)delta
mod:
add.l D1,